#include <algorithm>

#include "Game.hpp"
#include "ScreenManager.hpp"
#include "GameScreen.hpp"

namespace fge
{
ScreenManager::ScreenManager(Game *game)
	: game(game)
{
}

ScreenManager::~ScreenManager()
{
	std::list<GameScreen*>::iterator end = screens.end();
	for(std::list<GameScreen*>::iterator iterator = screens.begin(); iterator != end; ++iterator)
	{
		if(!(*iterator)->IsManaged())
			delete (*iterator);
	}
}

void ScreenManager::LoadContent()
{
	// todo: figure out where LoadContent should be called
	// it was being called here and in AddScreen, which is bad.
	// commenting out here, for now.
	//std::list<GameScreen*>::iterator end = screens.end();
	//for(std::list<GameScreen*>::iterator iterator = screens.begin(); iterator != end; ++iterator)
	//{
	//	(*iterator)->LoadContent();
	//}
}

void ScreenManager::UnloadContent()
{
	std::list<GameScreen*>::iterator end = screens.end();
	for(std::list<GameScreen*>::iterator iterator = screens.begin(); iterator != end; ++iterator)
	{
		(*iterator)->UnloadContent();
	}
}

void ScreenManager::Update(float deltaSeconds)
{
	std::list<GameScreen*>::iterator iterator = screens.begin();
	while(iterator != screens.end())
	{
		if((*iterator)->NeedsRemoved())
			RemoveScreen(*iterator++);
		else
			++iterator;
	}

	screensToUpdate.clear();
	screensToUpdate = screens;

	GameScreen *waitingScreen = NULL;

	bool foundTransitionOff = false;
	bool hasFocus = true;//todo: need to know about this Game.IsActive;
	bool isCovered = false;

	while (screensToUpdate.size() > 0)
	{
		GameScreen *screen = screensToUpdate.back();
		screensToUpdate.pop_back();

		if (screen->GetScreenState() == ScreenState_Waiting)
		{
			if (waitingScreen == NULL)
			{
				waitingScreen = screen;
				isCovered = true;
				hasFocus = false;
			}
		}
		else if (screen->GetScreenState() != ScreenState_Hidden ||
			(screen->GetScreenState() == ScreenState_Hidden && waitingScreen == NULL))
		{
			screen->Update(deltaSeconds, hasFocus, isCovered);

			if (screen->GetScreenState() == ScreenState_TransitionOn || screen->GetScreenState() == ScreenState_Active)
			{
				hasFocus = false;

				if (!screen->IsPopup())
					isCovered = true;
			}
			else if (screen->GetScreenState() == ScreenState_TransitionOff)
			{
				foundTransitionOff = true;
			}
		}
	}

	if (waitingScreen != NULL && foundTransitionOff == false)
	{
		waitingScreen->Update(deltaSeconds, true, false);
	}
}

void ScreenManager::Draw()
{
	std::list<GameScreen*>::iterator end = screens.end();
	for(std::list<GameScreen*>::iterator iterator = screens.begin(); iterator != end; ++iterator)
	{
		GameScreen *screen = *iterator;
		if (screen->GetScreenState() == ScreenState_Hidden ||
			screen->GetScreenState() == ScreenState_Waiting)
			continue;
		(*iterator)->Draw();
	}
}

void ScreenManager::AddScreen(GameScreen *gameScreen)
{
	gameScreen->SetScreenManager(this);

	if (gameScreen->IsPopup())
		gameScreen->SetScreenState(ScreenState_TransitionOn);
	else
		gameScreen->SetScreenState(ScreenState_Waiting);

	gameScreen->LoadContent();

	screens.push_back(gameScreen);
}

void ScreenManager::RemoveScreen(GameScreen *gameScreen)
{
	gameScreen->UnloadContent();

	screens.remove(gameScreen);

	if(!gameScreen->IsManaged())
		delete gameScreen;
}

}

